/** 
 * File: StatManager.java
 * @author: Adam Phung
 * Date Created: Dec 4, 2012
 * Date Modified: Dec 4, 2012 
 * Description: Provides stats for different activities
 */
package edu.bu.cs673.superkids123.children.DataObjectAccess;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import edu.bu.cs673.superkids123.children.model.CompletedGame;
import edu.bu.cs673.superkids123.children.model.CompletedLesson;
import edu.bu.cs673.superkids123.children.model.Game;
import edu.bu.cs673.superkids123.children.model.Lesson;
import edu.bu.cs673.superkids123.common.model.AchievementRule.Activity;
import edu.bu.cs673.superkids123.common.model.Child;

// TODO: Auto-generated Javadoc
/**
 * The Class StatManager.
 */
public class StatManager {

	/**
	 * Returns the play time of passed in activity.
	 * Non-valid activities (Any- prefix) will return 0 time.
	 *
	 * @param child the child
	 * @param activity the activity
	 * @return the play time
	 */
	public static Date getPlayTime(Child child, Activity activity) {
		
		List<CompletedLesson> lessons = ReportManager.getAllChildCompletedLessons(child, true);
		List<CompletedGame> games = ReportManager.getAllChildCompletedGames(child, true);
		long time = 0;
		
		switch(activity) {
		case All:
			for (CompletedLesson lesson : lessons) {
				time += (lesson.getEndDate().getTime() - lesson.getStartDate().getTime());
			}
			for (CompletedGame game : games) {
				time += (game.getEndDate().getTime() - game.getStartDate().getTime());
			}
			return new Date(time);
		case AllLessons:
			for (CompletedLesson lesson : lessons) {
				time += (lesson.getEndDate().getTime() - lesson.getStartDate().getTime());
			}
			return new Date(time);
		case AllGames:
			for (CompletedGame game : games) {
				time += (game.getEndDate().getTime() - game.getStartDate().getTime());
			}
			return new Date(time);
		case LessonCount:
			for (CompletedLesson lesson : lessons) {
				if (lesson.getLesson().getName().contains("Count")) {
					time += (lesson.getEndDate().getTime() - lesson.getStartDate().getTime());
				}
			}
			return new Date(time);
		case LessonAdd:
			for (CompletedLesson lesson : lessons) {
				if (lesson.getLesson().getName().contains("Add")) {
					time += (lesson.getEndDate().getTime() - lesson.getStartDate().getTime());
				}
			}
			return new Date(time);
		case GameMatch:
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Match")) {
					time += (game.getEndDate().getTime() - game.getStartDate().getTime());
				}
			}
			return new Date(time);
		case GameMath:
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Math")) {
					time += (game.getEndDate().getTime() - game.getStartDate().getTime());
				}
			}
			return new Date(time);
		case GameArchery:
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Archery")) {
					time += (game.getEndDate().getTime() - game.getStartDate().getTime());
				}
			}
			return new Date(time);
		case GameClick:
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Click")) {
					time += (game.getEndDate().getTime() - game.getStartDate().getTime());
				}
			}
			return new Date(time);
		case GameSubtraction:
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Subtraction")) {
					time += (game.getEndDate().getTime() - game.getStartDate().getTime());
				}
			}
			return new Date(time);
		default: // Not Valid Activity for this Type
			System.out.println("Not Valid Activity for this type");
			break;
		}
		
		return new Date(0);
	}
	
	/**
	 * Returns an array with the scores of the passed in activity.
	 * Only valid on games, any non-valid Activity will return -1.
	 *
	 * @param child the child
	 * @param activity the activity
	 * @return the play scores
	 */
	public static int[] getPlayScores(Child child, Activity activity) {
		
		List<CompletedGame> games = ReportManager.getAllChildCompletedGames(child, true);
		List<Integer> scores = new ArrayList<Integer>();
		
		switch(activity) {
		case AnyGame:
			for (CompletedGame game : games) {
				scores.add(game.getScore());
			}
			break;
		case GameMatch:
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Match"))
					scores.add(game.getScore());
			}
			break;
		case GameMath:
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Math"))
					scores.add(game.getScore());
			}
			break;
		case GameArchery:
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Archery"))
					scores.add(game.getScore());
			}
			break;
		case GameClick:
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Click"))
					scores.add(game.getScore());
			}
			break;
		case GameSubtraction:
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Subtraction"))
					scores.add(game.getScore());
			}
			break;
		default: // Not Valid Activity
			System.out.println("Not Valid Activity for this type");
			break;
		}
		
		// Convert to array
		int[] output = new int[scores.size()];
		for (int i = 0; i < output.length; i++) 
			output[i] = scores.get(i);
		
		return output;
	}
	
	/**
	 * Gets the play count for the passed in Activity.
	 * Activities with the "Any-" prefix will return the
	 * highest play count for any single activity.
	 *
	 * @param child the child
	 * @param activity the activity
	 * @return integer: play count
	 */
	public static int getPlayCount(Child child, Activity activity) {
		
		List<CompletedLesson> lessons = ReportManager.getAllChildCompletedLessons(child, true);
		List<CompletedGame> games = ReportManager.getAllChildCompletedGames(child, true);
		
		switch(activity) {
		case All:
			return lessons.size() + games.size();
		case AllLessons:
			return lessons.size();
		case AllGames:
			return games.size();
		case AnyGame:
			HashMap<Game, Integer> gameCount = new HashMap<Game, Integer>();
			for (CompletedGame game : games) {
				if (gameCount.containsKey(game.getGame())) {
					int count = gameCount.get(game.getGame());
					gameCount.put(game.getGame(), ++count);
				} else {
					gameCount.put(game.getGame(), 1);
				}
			}
			
			int highest = 0;
			Iterator it = gameCount.entrySet().iterator();
			while (it.hasNext()) {
		        Map.Entry pairs = (Map.Entry)it.next();
		        int count = (Integer) pairs.getValue();
		        highest = count > highest ? count : highest; 
		        it.remove(); // avoids a ConcurrentModificationException
			}
			return highest;	
		case AnyLesson:
			HashMap<Lesson, Integer> lessonCount = new HashMap<Lesson, Integer>();
			for (CompletedLesson lesson : lessons) {
				if (lessonCount.containsKey(lesson.getLesson())) {
					int count = lessonCount.get(lesson.getLesson());
					lessonCount.put(lesson.getLesson(), ++count);
				} else {
					lessonCount.put(lesson.getLesson(), 1);
				}
			}
			
			highest = 0;
			it = lessonCount.entrySet().iterator();
			while (it.hasNext()) {
		        Map.Entry pairs = (Map.Entry)it.next();
		        int count = (Integer) pairs.getValue();
		        highest = count > highest ? count : highest; 
		        it.remove(); // avoids a ConcurrentModificationException
			}
			return highest;			
		case LessonCount:
			int count = 0;
			for (CompletedLesson lesson : lessons) {
				if (lesson.getLesson().getName().contains("Count")) {
					count++;
				}
			}
			return count;
		case LessonAdd:
			count = 0;
			for (CompletedLesson lesson : lessons) {
				if (lesson.getLesson().getName().contains("Add")) {
					count++;
				}
			}
			return count;
		case GameMatch:
			count = 0;
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Match")) {
					count++;
				}
			}
			return count;
		case GameMath:
			count = 0;
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Math")) {
					count++;
				}
			}
			return count;
		// TODO: Get stats for these activities
		case GameArchery:
			count = 0;
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Archery")) {
					count++;
				}
			}
			return count;
		case GameClick:
			count = 0;
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Click")) {
					count++;
				}
			}
			return count;
		case GameSubtraction:
			count = 0;
			for (CompletedGame game : games) {
				if (game.getGame().getName().contains("Subtraction")) {
					count++;
				}
			}
			return count;
		default:
			break;
		}
		
		return 0;
	}
}
